﻿namespace SharePointRing.Framework.Helpers
{
    using Framework.Model;
    using Microsoft.SharePoint.Administration;
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;

    public static class SPWebApplicationHelper
    {
        public static void CreateWebApplication(WebApplicationInfo webApplicationInfo, bool provisionGlobally)
        {
            var webAppBuilder = new SPWebApplicationBuilder(SPFarm.Local)
            {
                HostHeader = webApplicationInfo.HostHeader,
                Port = webApplicationInfo.Port,
                RootDirectory = new DirectoryInfo(webApplicationInfo.IisPath),
                ApplicationPoolId = webApplicationInfo.ApplicationPoolId,
                CreateNewDatabase = webApplicationInfo.CreateNewContentDatabase,
                DatabaseServer = webApplicationInfo.DatabaseServer,
                DatabaseName = webApplicationInfo.DatabaseName,
                UseNTLMExclusively = webApplicationInfo.UseNTLMExclusively,
                AllowAnonymousAccess = webApplicationInfo.AllowAnonymousAccess
            };

            if (webApplicationInfo.CreateNewApplicationPool)
            {
                webAppBuilder.ApplicationPoolUsername = webApplicationInfo.ApplicationPoolUsername;
                webAppBuilder.ApplicationPoolPassword = webApplicationInfo.ApplicationPoolPassword;
            }

            SPWebApplication newApplication = webAppBuilder.Create();
            if (provisionGlobally)
                newApplication.ProvisionGlobally();
            else
                newApplication.Provision();
        }

        public static int GetRandomAvailablePort()
        {
            int result = -1;
            int retries = 100;
            var ports = GetUsedPortsList();

            while (result == -1 && retries > 0)
            {
                Random random = new Random();

                result = random.Next(65535 - 1025) + 1025;
                if (ports.Contains(result))
                    result = -1;
                retries--;
            }

            return result;
        }

        private static List<int> AddElementToListIfItDoesNotExist(List<int> list, int element)
        {
            if (!list.Contains(element))
                list.Add(element);

            return list;
        }

        public static List<int> GetUsedPortsList()
        {
            var ports = new List<int>();
            SPFarm farm = SPFarm.Local;
            SPWebService service = farm.Services.GetValue<SPWebService>(string.Empty);
            foreach (SPWebApplication webApp in service.WebApplications)
            {
                ports = AddElementToListIfItDoesNotExist(ports, webApp.GetResponseUri(SPUrlZone.Default).Port);
                ports = AddElementToListIfItDoesNotExist(ports, webApp.GetResponseUri(SPUrlZone.Intranet).Port);
                ports = AddElementToListIfItDoesNotExist(ports, webApp.GetResponseUri(SPUrlZone.Internet).Port);
                ports = AddElementToListIfItDoesNotExist(ports, webApp.GetResponseUri(SPUrlZone.Extranet).Port);
                ports = AddElementToListIfItDoesNotExist(ports, webApp.GetResponseUri(SPUrlZone.Custom).Port);
            }

            return ports;
        }

        public static List<WebApplicationInfo> GetAllWebApplications()
        {
            var webApps = new List<WebApplicationInfo>();
            SPFarm farm = SPFarm.Local;
            SPWebService service = farm.Services.GetValue<SPWebService>(string.Empty);
            foreach (SPWebApplication webApp in service.WebApplications)
            {
                var responseUri = webApp.GetResponseUri(SPUrlZone.Default);
                webApps.Add(new WebApplicationInfo() { Port = responseUri.Port });
            }

            return webApps;
        }
    }
}
